<?php 

/* 
	pats parastakais objekts
*/

class ObjectModule
{
	
	public $error = array();
	
	public $id;
	
	public $tableName;
	
	public $allowedParams = array('sort', 'direction', 'limit', 'id');
	
	public $presave, $postsave; //pre & podt save actions
	
	public $cleanup; 
	
	/* CONSTRUCT */
	public function __construct($id = null)
	{
		if(!$id)
		{
			return;
		}
		
		$this->id = $id;
		//$this->loadValues();
		
		//cleanup function
		if($this->cleanup != NULL)
		{
			$variables = call_user_func(array($this, $this->presave), $variables);
		}
		
		
	}
	
	
	/* PUBLIC METHODS */
	public function Save($variables)
	{
		
		//$variables = _utility::addslashes_deep($variables);
		
		if($this->presave != NULL)
		{
			$variables = call_user_func(array($this, $this->presave), $variables);
		}
		
		$variables = $this->validate($variables);
		
		
		$tableName = TABLEPREFIX . $this->tableName; 
		
		if(isset($this->id) && $this->id > 0)
		{
			$variables['id'] = $this->id;
		}
		
		$saveData = $this->removeFieldTypeFields($variables);
		
		
		
		foreach($this->fields as $key=>$val)
		{
			//catch delete
			if($val['type'] == 'file' && isset($variables[$key.'_delete']) && $variables[$key.'_delete'] == '1')
			{
				$saveData[$key] = 0;
				if(empty($this->error))
				{
					$this->deleteFile($this->$key);
				}
				unset($saveData[$key.'_delete']);
			}
			
			//cleanup save params
			if($val['type'] == 'file' && isset($variables[$key.'_delete']))
			{
				$check = true;
				unset($saveData[$key.'_delete']);
				if(is_null($saveData[$key]))
				{
					$saveData[$key] = '0';
				}
			}
			
		}
		
		
		if(empty($this->error))
		{
			
			dbReplace($saveData, $tableName);
			$this->loadUpdated();
			$needupdate = false;
			
			//catch files
			foreach($this->fields as $key=>$val)
			{
				if($val['type']=='file' && is_array($variables[$key]) && $variables[$key]['error'] == '0')
				{
					$id = $this->uploadFile($variables[$key]); 
					if($id)
					{
						$saveData[$key] = $id;
						$needupdate = true;
						$saveData['id'] = $this->id;
					}
				}
	
			}
			
			if($needupdate)
			{
				dbReplace($saveData, $tableName);
			}
			
			if($this->postsave != NULL)
			{
				$variables = call_user_func(array($this, $this->postsave));
			}
		
		}
		
		
		
		
		return;
	}
	
	private function cleanupAfterDelete($data)
	{
		
	}
	
	private function uploadFile($fileData)
	{
		$folder = strtolower(get_class($this));
		$savePath = PATH . 'content/' . $folder . '/';
		if(!file_exists($savePath))
		{
			mkdir($savePath);
		}
		
		$newName = $this->generateFileName($fileData['name']);
		
		if(copy($fileData['tmp_name'], $savePath . $newName))
		{
			$dataArray = array('originalFileName' => $fileData['name'] ); 
			$dIn = array(
				'file' 		=> $newName,
				'object'	=> $folder,
				'object_id' => $this->id,
				'date_time' => '__NOW()__',
				'ip_addr'	=> $_SERVER['REMOTE_ADDR'],
				'data' 		=> serialize($dataArray),
			);
			
			dbInsert($dIn, 'attachments');
			
			$q = 'SELECT id FROM attachments order by id DESC limit 1';
			$r = returnFirstRow($q);
			$id = $r['id'];
			
			return $id;
			
		}
		
		return false;
	
	}
	
	
	public function removeFieldTypeFields($variables)
	{
		foreach($this->fields as $key=>$val)
		{
			if($val['type'] == 'file' && is_array($variables[$key]) && $variables[$key]['error'] == '0')
			{
				$variables[$key] = 0;
			}
			elseif($val['type'] == 'file' && is_array($variables[$key]) && $variables[$key]['error'] == '4') // - no change
			{
				$variables[$key] = $this->$key;
			}
		}
		
		return $variables;
		
	}
	
	function generateFileName($name)
	{
    	$sufix = $this->getSufix($name);
    	$newname = date('YmdHis') . '-' . rand(1000, 9999) . $sufix;
    	return $newname;
	}
    
	function getSufix($name)
	{
   		return strtolower(substr($name, strrpos($name,'.')));
	}
	
	
	public function validate($variables)
	{
		$allow = true;		
		$data = array();
		
		foreach($this->fields as $key => $field)
		{
			
			if(!isset($variables[$key]) && isset($field['required']) && $field['required']==true)
			{
				//error
				$this->error[$key] = $key;
			}
			
			else
			{
				//validate //TODO additional checks & custom fields
				$value = '';
				if(isset($variables[$key]))
				{
					$value = $variables[$key]; 
				}
				
				if(isset($field['required']) && $field['required']==1 && !$this->validateItem($field['type'], $value))
				{
					//maker error
					$this->error[$key] = $key;
				}
				else
				{
					//pass 
					//serialize array
					if($field['type'] == 'array')
					{
						$value = serialize($value);
					}
					$data[$key] = $value;
				}
			}
			
			//password field
			if($field['type'] == 'password' && $this->id != 0 && $variables[$key]=='')
			{
				$this->loadValues();
				unset($this->error[$key]);
				$data[$key] = $this->$key;
			}
			elseif
			(
				($field['type'] == 'password' && $this->id != 0 && $variables[$key]!='') ||
				($field['type'] == 'password' && $this->id == 0)
			)
			{
				if($variables[$key] != $variables[$key . '_repeat'])
				{
					$this->error[$key] = $key;
				}
				else
				{
					$data[$key] = sha1($variables[$key]);
					//unset($variables[$key . '_repeat']);
				}
			}
			
			

			//file field for save / delete 
			if(isset($variables[$key.'_delete']))
			{
				$data[$key.'_delete'] = $variables[$key.'_delete'];
			}
			
		}
		
		
		//debug($data);
				
		return $data;
	
	}
	
	
	public function getList($params = array())
	{
		
		$params = $this->cleanupParams($params);
		
		$q = array();
		$q['select'][] = 's.*';
		$q['from'] = $this->tableName . ' As s';
		
		if(isset($params['sort']) && in_array($params['sort'], $this->getListFields()))
		{
			$direction = 'ASC';
			if(isset($params['direction']) && $params['direction'] == '1')
			{
				$direction = 'DESC';	
			}
			$q['order'] = $params['sort'] . ' ' . $direction;
		}
		
		if(isset($params['limit']))
		{
			$q['limit'] = $params['limit'];
		}
		
		if(!isset($q['order']))
		{
			$q['order'] = 'id DESC';
		}
		
		if(isset($params['id']))
		{
			$q['where'][] = 's.id = ' . $params['id']; 
		}
		
		
		//get auto joins
		$joinLetters = array('q', 'w', 'e', 'r', 't', 'y');
		$ind = 0; 
		foreach($this->fields as $key=>$item)
		{
			//objectList
			if($item['type'] == 'objectList')
			{
				$obj = new $item['object'];
				$q['leftJoin'][] = $obj->tableName . ' AS ' . $joinLetters[$ind] . ' ON (s.' . $key . ' = ' . $joinLetters[$ind] . '.' . $item['key'] . ')';
				$q['select'][] = $joinLetters[$ind] . '.' . $item['value'] . ' as ' . $key . '_VALUE'; 
				$ind++;
			}
			
			//file
			if($item['type'] == 'file')
			{
				$q['leftJoin'][] = 'attachments AS ' . $joinLetters[$ind] . ' ON(s.' . $key . ' = ' . $joinLetters[$ind] . '.id)';
				$q['select'][] = $joinLetters[$ind] . '.file as ' . $key . '_VALUE';  
 				$ind++;
			}
			
		}
		
		return dbExecute($q, get_class($this));
		
	}
	
	
	public function validateItem($type, $data)
	{
		//TODO create class.Validate.php -> Validate::Text($value);
		switch ($type)
		{
			case'array':
				return true;
			break;
			default:
				//text
				if($data!='')
				{
					return true;
				}
					
			break;
		} 
		
		
		return false;
		
	}
	
	private function loadUpdated()
	{
		
		if($this->id > 0)
		{
			$id = $this->id;
		}
		else
		{
			$q = array();
			$q['select'][] = 'id';
			$q['from'] = $this->tableName;
			$q['limit'] = 1;
			$q['order'] = 'id DESC';
			
			$r = returnFirstRow($q);
			$id = $r['id'];
		}
		
		$this->id = $id;
		$this->loadValues();
		
	}
	
	
	public function loadValues()
	{
		$class = get_class($this);
		
		if($this->id!=null)
		{
			$params = array('id' => $this->id);
			$list = $this->getList($params);
			$values = $list[0];
		}
		else
		{
			$values = $this;
		}

		
		//TODO: refactor
		$props = get_class_vars(get_class($this));
		foreach($props as $prop => $value)
		{
			//$value = _utility::stripslashes_deep($value);
			$value = $values->$prop;
			if( 
				((isset($values->fields[$prop]['type']) && $values->fields[$prop]['type'] == 'array') ) 
				||
				(isset($values->fields[$prop]['serialized']) && is_string($value))
			) 
			{
				$value = _utility::mb_unserialize($value);
				$value = _utility::stripslashes_deep($value);
			}
			
			$fakeField = $prop.'_VALUE';
			
			if(isset($values->$fakeField))
			{
				$this->$fakeField = $values->$fakeField;
			}
			
			$this->$prop = $value;
			
		}
		
	}
	
	public function getListFields()
	{
		if(!is_array($this->fields))
		{
			return;
		}
		$forbiddenFields = array('textarea', 'richtext', 'array', 'file', 'password');
		$out = array();
 		foreach($this->fields as $key => $item)
		{
			if(!in_array($item['type'], $forbiddenFields) && !isset($item['notInList']))
			{
				$out[] = $key;
			}
		}
		
		return $out;
	
	}
	
	
	public function Delete()
	{
		
		foreach($this->fields as $key=>$val)
		{
			if($val['type']=='file' && $this->$key != 0)
			{
				$this->deleteFile($this->$key);
			}
		}
		dbDelete(array('id', $this->id), $this->tableName);
		return;
	}
	
	
	private function cleanupParams($params)
	{
		
		foreach($params as $key=>$item)
		{
			if(!in_array($key, $this->allowedParams))
			{
				unset($params[$key]);
			}
		}
		
		return $params;
		
	}
	
	public function getFieldValue($field)
	{
		$f = $this->fields[$field];
		
		if($f['type']=='checkbox')
		{
			if($this->$field == 1)
			{
				return "*";
			}
			else
			{
				return '';
			}
		}
		
		if($f['type'] == 'objectList')
		{
			$key = $field . '_VALUE';
			 
			return $this->$key;
		}
		
		return $this->$field;
		
	}
	
	public function getAttachmentsPath()
	{
		$path = PATH . 'content/' . strtolower(get_class($this)) . '/';
		return $path;
	} 
	
	public function getAttachmentsUrl()
	{
		$url = WWW . 'content/' . strtolower(get_class($this)) . '/';
		return $url;
	} 
	
	private function deleteFile($id)
	{
		if($id==null)
		{
			return;
		}
		
		$q = array();
		$q['select'][] = 'a.*';
		$q['from'] = 'attachments AS a';
		$q['where'][] = 'a.id=' . $id;
		
		$r = returnFirstRow($q);
		
		$file = $this->getAttachmentsPath() . $r['file'];
		if(file_exists($file))
		{
			unlink($file);
		}
		
		dbExecute('DELETE FROM attachments WHERE id= ' . $id);
		
		return true;
		
	}
	
	public function getClassName()
	{
		//debug($this);
		//return strtolower(get_class($this));
	}
		
}




?>